<template>
    <div class="form-edit-container">
        <div class="left-board">
            <el-scrollbar class="left-scrollbar">
                <div class="components-list">
                    <div v-for="(item, listIndex) in leftComponents" :key="listIndex">
                        <div class="components-title">
                            <form-svg-icon name="component" />
                            {{ item.title }}
                        </div>
                        <draggable
                            :clone="cloneComponent"
                            :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
                            :list="item.list"
                            :move="handleMove"
                            :sort="false"
                            class="components-draggable"
                            draggable=".components-item"
                            @end="onEnd"
                        >
                            <div
                                v-for="(element, index) in item.list"
                                :key="index"
                                class="components-item"
                                @click="addComponent(element)"
                            >
                                <div class="components-body">
                                    <form-svg-icon :name="element.config.tagIcon" />
                                    {{ element.config.label }}
                                </div>
                            </div>
                        </draggable>
                    </div>
                </div>
            </el-scrollbar>
        </div>
        <div class="center-board">
            <!--      <el-row class="operation-btn-view">-->
            <!--        <el-col :offset="20">-->
            <!--          <el-button icon="el-icon-top" type="text" @click="handleOpenImportItem">-->
            <!--            导入题目-->
            <!--          </el-button>-->
            <!--        </el-col>-->
            <!--      </el-row>-->
            <ImportFormItem ref="importItems" :form-key="formKey" @success="queryProjectItems" />
            <el-scrollbar ref="centerScrollbar" class="center-scrollbar">
                <el-row v-if="formConf" :gutter="formConf.gutter" class="center-board-row">
                    <el-row align="middle" justify="center" type="flex">
                        <el-col :span="20" class="text-center">
                            <h4 class="form-name-text" contenteditable="true"
                                @blur="(event)=>{
                                    formConf.title=event.target.innerText;
                                    saveProjectInfo()}"
                            >
                                {{ formConf.title }}
                            </h4>
                        </el-col>
                    </el-row>
                    <el-row v-if="questionMode" align="middle" justify="center" type="flex">
                        <el-col :span="23">
                            <tinymce v-if="editDescription" v-model="formConf.description"
                                     placeholder="请输入表单描述"
                                     @blur="editDescription=false" @input="saveProjectInfo"
                            />
                            <div v-else class="form-name-text"
                                 @click="editDescription=true" v-html="formConf.description"
                            />
                        </el-col>
                    </el-row>
                    <el-divider v-if="questionMode" />
                    <el-form
                        :disabled="formConf.disabled"
                        :label-position="formConf.labelPosition"
                        :label-width="formConf.labelWidth + 'px'"
                        :size="formConf.size"
                    >
                        <draggable :animation="340" :list="drawingList" :move="handleCenterMove" class="drawing-board"
                                   group="componentsGroup"
                                   @end="onItemEnd"
                        >
                            <form-item-layout
                                v-for="(item, index) in drawingList"
                                :key="item.renderKey"
                                :active-id="activeId"
                                :current-item="item"
                                :drawing-list="drawingList"
                                :form-conf="formConf"
                                :index="index"
                                @activeItem="activeFormItem"
                                @change="updateProjectItemInfo"
                                @changeLabel="changeLabel"
                                @copyItem="drawingItemCopy"
                                @deleteItem="drawingItemDelete"
                            />
                        </draggable>
                        <div v-show="!drawingList.length" class="empty-info">
                            <img
                                src=""
                            >
                            <p>从左侧拖入或点选组件进行表单设计</p>
                        </div>
                    </el-form>
                </el-row>
            </el-scrollbar>
        </div>
        <right-panel
            :active-data="activeData"
            :form-conf="formConf"
            :show-field="!!drawingList.length"
            @tag-change="tagChange"
            @add-fields="handleAddFields"
            @data-change="handleActiveDataChange"
        />
    </div>
</template>

<script>
import draggable from 'vuedraggable'
import FormItemLayout from './FormItemLayout'
import RightPanel from './RightPanel'
import tinymce from '../../components/tinymce/index'
import FormSvgIcon from '../../components/SvgIcon/index'
import ImportFormItem from './ImportFormItem'
import {debounce} from 'throttle-debounce'
import {allComponents, formConf, getComponentsObj} from '../../components/GenerateForm/config'
import _ from 'lodash'
import '../../assets/icons'
import {deepClone} from '../../utils'
import {saveDrawingList} from '../../utils/db'
import {dbDataConvertForItemJson, formItemConvertData} from '../../utils/convert'
import {
    createProjectItem,
    deleteProjectItem,
    queryProject,
    queryProjectItemList,
    sortProjectItem,
    stopPublishFormRequest,
    updateProject,
    updateProjectItem
} from '../../api/index.js'

let oldActiveId
let tempActiveData

export default {
    name: 'FormEditor',
    components: {
        FormItemLayout,
        draggable,
        RightPanel,
        FormSvgIcon,
        ImportFormItem,
        tinymce
    },
    props: {
        // 问卷模式 给tduck问卷使用
        questionMode: {
            type: Boolean,
            default: false
        }
    },
    data() {
        return {
            formConf: null,
            editDescription: true,
            tempFormConf: {},
            labelWidth: 100,
            drawingList: [],
            activeId: 0,
            activeData: null,
            saveDrawingListDebounce: debounce(340, saveDrawingList),
            formKey: null,
            leftComponents: allComponents
        }
    },
    computed: {},
    watch: {
        'activeData.config.label': function(val, oldVal) {
            if (
                this.activeData.placeholder === undefined
                || !this.activeData.config.tag
                || oldActiveId !== this.activeId
            ) {
                return
            }
            this.activeData.placeholder = this.activeData.placeholder.replace(oldVal, '') + val
        },
        activeId: {
            handler(val) {
                oldActiveId = val
            },
            immediate: true
        },
        drawingList: {
            handler(val) {
                this.saveDrawingListDebounce(val, this.formKey)
            },
            deep: true
        }
    },
    mounted() {
        // 复制对象 避免修改改变原始对象
        this.formConf = JSON.parse(JSON.stringify(formConf))
        // 项目key
        this.formKey = this.$route.query.key
        this.formConf.formKey = this.formKey
        // 从服务端获取
        this.queryProjectItems()
        this.queryProject()
    },
    methods: {
        // 获取表单配置
        queryProject() {
            queryProject(this.formKey)
                .then(res => {
                    this.tempFormConf = res.data
                    this.formConf.title = res.data.name
                    this.formConf.description = res.data.description
                })
        },
        saveProjectInfo: debounce(430, true, function() {
            updateProject({
                key: this.formKey,
                name: this.formConf.title,
                description: this.formConf.description
            })
                .then(() => {

                })
        }),
        // 处理已经发布的表单
        async handleCheckPublicForm() {
            let noPublish = true
            if (this.tempFormConf.status == 2) {
                noPublish = false
                await this.$confirm('该表单已经发布，继续编辑将会停止发布，是否确认？', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(async() => {
                    await stopPublishFormRequest({key: this.formKey})
                    await this.queryProject()
                    noPublish = true
                }).catch(() => {
                    noPublish = false
                })
            }
            return noPublish
        },
        handleActiveDataChange(val) {
            // 特殊处理子表单 使修改的数据为子表单组件本身
            if (val.isChild) {
                let parentItem = val.parentItem
                let tempVal = deepClone(val)
                delete tempVal.parentItem
                delete tempVal.childIndex
                parentItem.childList[val.childIndex] = tempVal
                val = parentItem
            }
            this.updateProjectItemInfo(val)
        },
        updateProjectItemInfo: debounce(430, true, function(val) {
            const data = formItemConvertData(val, this.formKey)
            updateProjectItem(data)
                .then(() => {

                })
        }),
        deleteProjectItemInfo(val) {
            const data = formItemConvertData(val, this.formKey)
            deleteProjectItem(data)
                .then(() => {
                })
        },
        async saveProjectItemInfo(item) {
            let isSuccess = false
            const params = formItemConvertData(item, this.formKey)
            const pItem = item
            await createProjectItem(params)
                .then(res => {
                    pItem.sort = res.data.sort
                    isSuccess = true
                })
            // 如果是分页组件 刷新所有分页的页码
            if (item.typeId === 'PAGINATION') {
                this.updatePaginationList()
            }
            return isSuccess
        },
        updatePaginationList() {
            // 页总数
            const {length} = this.drawingList.filter(item => item.typeId === 'PAGINATION')
            let curr = 1
            this.drawingList.forEach((item, index) => {
                if (item.typeId === 'PAGINATION') {
                    item.totalPageNum = length
                    item.currPageNum = curr++
                    this.$set(this.drawingList, index, item)
                }
            })
        },
        queryProjectItems() {
            queryProjectItemList({key: this.formKey})
                .then(res => {
                    this.drawingList = res.data.map(item => dbDataConvertForItemJson(item))
                    // 更新分页
                    this.updatePaginationList()
                })
        },
        activeFormItem(currentItem) {
            this.activeData = currentItem
            this.activeId = currentItem.config.formId
        },
        changeLabel(currentItem, value) {
        },
        handleMove(e, originalEvent) {
            if (this.tempFormConf.status == 2) {
                this.handleCheckPublicForm()
                return false
            }
            return true
        },
        onEnd(obj) {
            if (obj.from !== obj.to) {
                this.activeData = tempActiveData
                this.activeId = `${_.toLower(tempActiveData.typeId)}-${new Date().getTime()}`
                // 拖拽到子表单不单独保存
                if (obj.to.className === 'list-main') {
                    return
                }
                this.saveProjectItemInfo(tempActiveData)
                    .then(() => {
                        this.onItemEnd(obj)
                    })
            }
        },
        handleCenterMove(obj) {
            // 不允许拖到子表单
            if (obj.to.className === 'list-main') {
                return false
            }
        },
        onItemEnd(obj) {
            const params = {formKey: this.formKey}
            if (this.drawingList[obj.newIndex - 1]) {
                const sort1 = this.drawingList[obj.newIndex - 1].sort
                params.beforePosition = sort1
            }
            if (this.drawingList[obj.newIndex + 1]) {
                const sort2 = this.drawingList[obj.newIndex + 1].sort
                params.afterPosition = sort2
            }
            params.formItemId = this.drawingList[obj.newIndex].config.formId
            if (params.beforePosition || params.afterPosition) {
                sortProjectItem(params)
                    .then(res => {
                        this.drawingList[obj.newIndex].sort = res.data.sort
                    })
            }
        },
        addComponent(item) {
            this.handleCheckPublicForm().then(res => {
                if (res) {
                    const clone = this.cloneComponent(item)
                    this.saveProjectItemInfo(clone)
                    this.drawingList.push(clone)
                    this.activeFormItem(clone)
                    // 滑动定位到底部
                    this.scrollToBottom()
                }
            })
        },
        scrollToBottom() {
            const div = this.$refs.centerScrollbar.$refs.wrap
            this.$nextTick(() => {
                div.scrollTop = div.scrollHeight
            })
        },
        cloneComponent(origin) {
            const clone = deepClone(origin)
            const config = clone.config
            config.span = this.formConf.span
            this.createIdAndKey(clone)

            // 文件上传组件处理
            if (clone.action) {
                clone.action += this.formKey
            }
            clone.placeholder !== undefined && (clone.placeholder += config.label)
            tempActiveData = clone
            return tempActiveData
        },
        createIdAndKey(item) {
            const config = item.config
            // 使用组件类型+时间戳 为ID
            config.formId = `${_.toLower(item.typeId)}-${new Date().getTime()}`
            config.renderKey = `${config.formId}${+new Date()}` // 改变renderKey后可以实现强制更新组件
            item.vModel = `${config.formId}`
            return item
        },
        empty() {
            this.$confirm('确定要清空所有组件吗？', '提示', {type: 'warning'})
                .then(
                    () => {
                        this.drawingList = []
                    }
                )
        },
        drawingItemCopy(item, list) {
            this.handleCheckPublicForm().then(res => {
                if (res) {
                    let clone = deepClone(item)
                    clone = this.createIdAndKey(clone)
                    list.push(clone)
                    this.activeFormItem(clone)
                    this.saveProjectItemInfo(clone)
                }
            })
        },
        drawingItemDelete(item, list) {
            this.handleCheckPublicForm().then(res => {
                if (res) {
                    const index = list.findIndex(val => val.config.formId === item.config.formId)
                    list.splice(index, 1)
                    this.$nextTick(() => {
                        const len = this.drawingList.length
                        if (len) {
                            this.activeFormItem(this.drawingList[len - 1])
                        }
                    })
                    this.deleteProjectItemInfo(item)
                }
            })
        },
        // 类型切换 弃用
        tagChange(newTag) {
            newTag = this.cloneComponent(newTag)
            const config = newTag.config
            newTag.vModel = this.activeData.vModel
            newTag.sort = this.activeData.sort
            config.formId = this.activeId
            config.span = this.activeData.config.span
            this.activeData.config.tag = config.tag
            this.activeData.config.tagIcon = config.tagIcon
            this.activeData.config.document = config.document
            this.activeData.typeId = newTag.typeId
            if (typeof this.activeData.config.defaultValue === typeof config.defaultValue) {
                config.defaultValue = this.activeData.config.defaultValue
            }
            Object.keys(newTag)
                .forEach(key => {
                    if (this.activeData[key] !== undefined) {
                        newTag[key] = this.activeData[key]
                    }
                })
            this.activeData = newTag
            this.updateProjectItemInfo(newTag)
            this.updateDrawingList(newTag, this.drawingList)
        },
        updateDrawingList(newTag, list) {
            const index = list.findIndex(item => item.config.formId === this.activeId)
            if (index > -1) {
                list.splice(index, 1, newTag)
            } else {
                list.forEach(item => {
                    if (Array.isArray(item.config.children)) this.updateDrawingList(newTag, item.config.children)
                })
            }
        },
        handleOpenImportItem() {
            this.$refs.importItems.showDialog()
        },
        // 创建Ocr识别所需要的存储字段 由Ocr字段抛出
        handleAddFields(val) {
            // 创建字段 保存识别返回字段和表单字段映射关系
            let fieldMapping = {}
            _.keys(val).forEach(key => {
                let field = val[key]
                console.log(field)
                console.log(getComponentsObj())
                let compo = getComponentsObj()[field.type]
                compo.config.label = field.label
                const clone = this.cloneComponent(compo)
                this.saveProjectItemInfo(clone)
                this.drawingList.push(clone)
                console.log(clone)
                fieldMapping[key] = clone.config.formId
            })
            this.activeData.fieldMapping = fieldMapping
            // 保存
            this.handleActiveDataChange(this.activeData)
        }
    }
}
</script>

<style lang="scss">
@import '../../assets/styles/home';
@import '../../assets/styles/index';
</style>
<style lang="scss" scoped>
.form-edit-container {
  overflow-x: hidden !important;
  height: calc(100vh - 60px);
}

.form-name-text:hover {
  border: 1px dashed #7b7b7b;
  min-height: 100px;
}

</style>
